﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace CC.Yacht.Windows.Forms
{
    public partial class DiceControl : UserControl
    {
        #region Constructor
        public DiceControl()
        {
            InitializeComponent();
            SuppressFaceChange = true;

            _DieControls = new List<DieControl> {_DieControl1, _DieControl2, _DieControl3, _DieControl4, _DieControl5};
        }
        #endregion

        #region Private Fields
        private Color _BorderColor = Color.Black;
        private bool _CanLock = true;
        private readonly List<DieControl> _DieControls;
        private readonly Dice _Dice = new Dice();
        private Color _DiceColor = Color.White;
        private Color _LockedBorderColor = Color.Gold;
        private Color _LockedDiceColor = Color.White;
        private Color _LockedForeColor = Color.Black;
        private bool _SuppressChangedEvent;
        #endregion

        #region Public Events
        public event EventHandler<DiceChangedEventArgs> Changed;
        #endregion

        #region Public Properties
        public Color BorderColor
        {
            get { return _BorderColor; }
            set { _BorderColor = value; UpdateDiceColors(); }
        }

        public bool CanLock
        {
            get { return _CanLock; }
            set { _CanLock = value; UpdateCanLock(); }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool CanRoll
        {
            get { return _Dice.CanRoll; }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Dice Dice
        {
            get
            {
                _Dice.Die1 = _DieControl1;
                _Dice.Die2 = _DieControl2;
                _Dice.Die3 = _DieControl3;
                _Dice.Die4 = _DieControl4;
                _Dice.Die5 = _DieControl5;

                return _Dice;
            }
        }
        
        public Color DiceColor
        {
            get { return _DiceColor; }
            set { _DiceColor = value; UpdateDiceColors(); }
        }
        
        public override Color ForeColor
        {
            get { return base.ForeColor; }
            set { base.ForeColor = value; UpdateDiceColors(); }
        }

        public Color LockedBorderColor
        {
            get { return _LockedBorderColor; }
            set { _LockedBorderColor = value; UpdateLockedColors(); }
        }
        
        public Color LockedDiceColor
        {
            get { return _LockedDiceColor; }
            set { _LockedDiceColor = value; UpdateLockedColors(); }
        }
        
        public Color LockedForeColor
        {
            get { return _LockedForeColor; }
            set { _LockedForeColor = value; UpdateLockedColors(); }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int RollCount 
        {
            get { return _Dice.RollCount; }
            set { _Dice.RollCount = value; } 
        }

        public bool SuppressFaceChange { get; set; }
        #endregion

        #region Private Event Handlers
        private void _DieControl_Changed(object sender, DieChangedEventArgs e)
        {
            if (!SuppressFaceChange || ((e.Event & DieChangedEvents.FaceChanged) != DieChangedEvents.FaceChanged))
            {
                OnChanged(new DiceChangedEventArgs(Dice));
            }
        }
        #endregion

        #region Private Methods
        private void UpdateCanLock()
        {
            foreach (DieControl dieControl in _DieControls)
            {
                dieControl.CanLock = _CanLock;                
            }
        }

        private void UpdateDiceColors()
        {
            foreach (DieControl dieControl in _DieControls)
            {
                dieControl.BorderColor = _BorderColor;
                dieControl.DieColor = _DiceColor;
                dieControl.ForeColor = ForeColor;
            }
        }

        private void UpdateLockedColors()
        {
            foreach (DieControl dieControl in _DieControls)
            {
                dieControl.LockedBorderColor = _LockedBorderColor;
                dieControl.LockedDieColor = _LockedDiceColor;
                dieControl.LockedForeColor = _LockedForeColor;
            }
        }
        #endregion

        #region Protected Methods
        protected void OnChanged(DiceChangedEventArgs eventArgs)
        {
            if (!_SuppressChangedEvent && Changed != null)
            {
                Changed(this, eventArgs);
            }
        }
        #endregion

        #region Public Methods
        public void Clear()
        {
            foreach (DieControl dieControl in _DieControls)
            {
                if (!dieControl.Locked)
                {
                    dieControl.Reset();
                }
            }
        }

        public void Reset()
        {
            _SuppressChangedEvent = true;

            foreach (DieControl dieControl in _DieControls)
            {
                dieControl.Reset();
            }

            RollCount = 0;
            
            _SuppressChangedEvent = false;

            //OnChanged(new DiceChangedEventArgs(Dice));
        }

        public void Roll()
        {
            bool originalCanLock = CanLock;

            CanLock = false;

            if (CanRoll)
            {
                Clear();

                for (int i = 0; i < _DieControls.Count; i++)
                {
                    if (!_DieControls[i].Locked)
                    {
                        _DieControls[i].Roll();
                    }
                }

                RollCount++;
            }

            CanLock = originalCanLock;
        }

        public void Roll(bool ignoreRollCount)
        {
            bool originalCanLock = CanLock;

            CanLock = false;

            if (ignoreRollCount || CanRoll)
            {
                Clear();

                for (int i = 0; i < _DieControls.Count; i++)
                {
                    if (!_DieControls[i].Locked)
                    {
                        _DieControls[i].Roll();
                    }
                }

                if (!ignoreRollCount)
                {
                    RollCount++;
                }
            }

            CanLock = originalCanLock;
        }

        public void UpdateDice(Dice dice)
        {
            _SuppressChangedEvent = true;

            for (int i = 0; i < _DieControls.Count; i++)
            {
                DieControl dieControl = _DieControls[i];

                if (dieControl.Face != dice[i].Face)
                {
                    dieControl.Face = dice[i].Face;
                }
                if (dieControl.Locked != dice[i].Locked)
                {
                    dieControl.Locked = dice[i].Locked;
                }
            }

            _SuppressChangedEvent = false;
        }
        #endregion
    }
}
